/*
 *  Licensed to the Apache Software Foundation (ASF) under one
 *  or more contributor license agreements.  See the NOTICE file
 *  distributed with this work for additional information
 *  regarding copyright ownership.  The ASF licenses this file
 *  to you under the Apache License, Version 2.0 (the
 *  "License"); you may not use this file except in compliance
 *  with the License.  You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing,
 *  software distributed under the License is distributed on an
 *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 *  KIND, either express or implied.  See the License for the
 *  specific language governing permissions and limitations
 *  under the License.
 *
 */
package com.example.mina2.test.performance;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.util.concurrent.atomic.AtomicInteger;

import org.apache.mina.core.buffer.IoBuffer;
import org.apache.mina.core.filterchain.DefaultIoFilterChainBuilder;
import org.apache.mina.core.service.IoHandlerAdapter;
import org.apache.mina.core.session.IdleStatus;
import org.apache.mina.core.session.IoSession;
import org.apache.mina.filter.codec.CumulativeProtocolDecoder;
import org.apache.mina.filter.codec.ProtocolCodecFactory;
import org.apache.mina.filter.codec.ProtocolCodecFilter;
import org.apache.mina.filter.codec.ProtocolDecoder;
import org.apache.mina.filter.codec.ProtocolDecoderOutput;
import org.apache.mina.filter.codec.ProtocolEncoder;
import org.apache.mina.transport.socket.nio.NioSocketAcceptor;

import com.example.mina2.test.Counter;
import com.example.mina2.test.MyCodec;

/**
 * An TCP server used for performance tests.
 * 
 * It does nothing fancy, except receiving the messages, and counting the number
 * of received messages.
 * 
 * @author <a href="http://mina.apache.org">Apache MINA Project</a>
 */
public class TcpServer extends IoHandlerAdapter {
	/** The listening port (check that it's not already in use) */
	public static final int PORT = 18567;

	/** The number of message to receive */
	public static final int MAX_RECEIVED = 100000;

	/** The starting point, set when we receive the first message */
	private static long t0;

	/** A counter incremented for every recieved message */
	private AtomicInteger nbReceived = new AtomicInteger(0);

	private Counter counter = new Counter();

	/**
	 * {@inheritDoc}
	 */
	@Override
	public void exceptionCaught(IoSession session, Throwable cause)
			throws Exception {
		cause.printStackTrace();
		session.closeNow();
	}

	/**
	 * {@inheritDoc}
	 */
	@Override
	public void messageReceived(IoSession session, Object message)
			throws Exception {
		// System.out.println((String) message);
		// IoBuffer buf = ((IoBuffer) message);
		// byte[] b = new byte[3];
		// buf.get(b);
		// System.out.println(new String(b));

		// IoBuffer buf = ((IoBuffer) message);
		// byte[] b = new byte[buf.remaining()];
		// buf.get(b);
		// System.out.println(new String(b));

		// System.out.println((String) message);
		counter.add();
	}

	/**
	 * {@inheritDoc}
	 */
	@Override
	public void sessionClosed(IoSession session) throws Exception {
		System.out.println("Session closed...");

		// Reinitialize the counter and expose the number of received messages
		System.out.println("Nb message received : " + nbReceived.get());
		nbReceived.set(0);
	}

	/**
	 * {@inheritDoc}
	 */
	@Override
	public void sessionCreated(IoSession session) throws Exception {
		System.out.println("Session created...");
	}

	/**
	 * {@inheritDoc}
	 */
	@Override
	public void sessionIdle(IoSession session, IdleStatus status)
			throws Exception {
		System.out.println("Session idle...");
	}

	/**
	 * {@inheritDoc}
	 * 
	 * @param session
	 *            the current seession
	 * @throws Exception
	 *             If something went wrong
	 */

	@Override
	public void sessionOpened(IoSession session) throws Exception {
		System.out.println("Session Opened...");
	}

	/**
	 * Create the TCP server
	 * 
	 * @throws IOException
	 *             If something went wrong
	 */
	public TcpServer() throws IOException {
		counter.start();
		NioSocketAcceptor acceptor = new NioSocketAcceptor();
		acceptor.setHandler(this);

		DefaultIoFilterChainBuilder chain = acceptor.getFilterChain();

		ProtocolCodecFactory codecFactory = new MyCodec();
		chain.addLast("codec", new ProtocolCodecFilter(codecFactory));

		// chain.addLast("codec", new ProtocolCodecFilter(new
		// TextLineCodecFactory()));

		acceptor.bind(new InetSocketAddress(PORT));

		System.out.println("Server started...");
	}

	/**
	 * The entry point.
	 * 
	 * @param args
	 *            The arguments
	 * @throws IOException
	 *             If something went wrong
	 */
	public static void main(String[] args) throws IOException {
		System.out.println("mina2 tcpserver start");
		new TcpServer();
	}
}
